package info.batcloud.fanli.api.security.filter;

import info.batcloud.fanli.api.security.handler.LoginAuthenticationFailureHandler;
import info.batcloud.fanli.api.security.handler.LoginAuthenticationSuccessHandler;
import info.batcloud.fanli.core.constants.MessageKeyConstants;
import info.batcloud.fanli.core.context.StaticContext;
import info.batcloud.fanli.core.exception.BizException;
import info.batcloud.fanli.core.service.SmsService;
import info.batcloud.fanli.core.service.UserService;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class PhoneLoginAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {

    @Inject
    private UserService userService;

    @Inject
    private LoginAuthenticationSuccessHandler loginAuthenticationSuccessHandler;

    @Inject
    private LoginAuthenticationFailureHandler loginAuthenticationFailureHandler;

    @Inject
    private SmsService smsService;

    public PhoneLoginAuthenticationProcessingFilter() {
        super("/login-phone");
        setAuthenticationDetailsSource(authenticationDetailsSource);
    }

    @PostConstruct
    public void afterPropertiesSet() {
        this.setAuthenticationSuccessHandler(loginAuthenticationSuccessHandler);
        this.setAuthenticationFailureHandler(loginAuthenticationFailureHandler);
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {

        String phone = request.getParameter("phone");
        String verifyCode = request.getParameter("verifyCode");

        UserDetails userDetails = userService.loadUserByUsername(phone);
        if (!smsService.validatePhoneCode(phone, verifyCode)) {
            throw new VerifyCodeNotValidException(StaticContext.messageSource.getMessage(MessageKeyConstants.PHONE_VERIFY_CODE_INVALID, null, null));
        }
        return new UsernamePasswordAuthenticationToken(userDetails, null,
                userDetails.getAuthorities());
    }

    public static class VerifyCodeNotValidException extends AuthenticationException {

        public VerifyCodeNotValidException(String msg) {
            super(msg);

        }
    }
}
